package com.niiwoo.civet.mobile.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.niiwoo.civet.base.utils.ProjectInfoUtil;
import com.niiwoo.civet.mobile.vo.request.loan.*;
import com.niiwoo.civet.mobile.vo.request.user.SpeedLoanCreditAmountReqeustVO;
import com.niiwoo.civet.mobile.vo.response.FastBorrowAccreditCityResponseVO;
import com.niiwoo.civet.mobile.vo.response.loan.*;
import com.niiwoo.civet.mobile.vo.response.user.SpeedLoanCreditAmountResponseVO;
import com.niiwoo.civet.mobile.vo.response.user.SpeedLoanCreditResultResponseVO;
import com.niiwoo.civet.trade.dto.request.SpeedLoanApplyForBackRequestDTO;
import com.niiwoo.civet.trade.dto.request.SpeedLoanApplyRequestDTO;
import com.niiwoo.civet.trade.dto.request.SpeedLoanPublishCheckRequestDTO;
import com.niiwoo.civet.trade.dto.request.loan.*;
import com.niiwoo.civet.trade.dto.response.SpeedLoanApplyCommonResponseDTO;
import com.niiwoo.civet.trade.dto.response.SpeedLoanConfigurationResponseDTO;
import com.niiwoo.civet.trade.dto.response.SpeedLoanCreditResultDTO;
import com.niiwoo.civet.trade.dto.response.SpeedLoanQueryResponseDTO;
import com.niiwoo.civet.trade.dto.response.loan.ConfirmResponseDTO;
import com.niiwoo.civet.trade.dto.response.loan.ContractPreviewInfoDTO;
import com.niiwoo.civet.trade.dto.response.statisticsinfo.FastBorrowAccreditCityResponseDTO;
import com.niiwoo.civet.trade.enums.ConfirmLoanSourceEnum;
import com.niiwoo.civet.trade.enums.ProjectApplyCheckTypeEnum;
import com.niiwoo.civet.trade.enums.ProjectTypeEnum;
import com.niiwoo.civet.trade.enums.RateConfigTypeEnum;
import com.niiwoo.civet.trade.service.loan.SpeedLoanDubboService;
import com.niiwoo.civet.user.dto.request.LaunchSpeedLoanCreditRequestDTO;
import com.niiwoo.civet.user.dto.response.LaunchSpeedLoanCreditDTO;
import com.niiwoo.civet.user.enums.PlatformTypeEnum;
import com.niiwoo.civet.user.service.UserCreditDubboService;
import com.niiwoo.tripod.provider.exception.BizException;
import com.niiwoo.tripod.web.util.PrincipalContext;
import com.niiwoo.tripod.web.util.RequestUtil;
import com.niiwoo.tripod.web.vo.Empty;
import com.niiwoo.tripod.web.vo.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * Created by ace on 2017/9/25.
 */
@Slf4j
@RestController
@RequestMapping("/speedLoan")
@Api(tags = "极速借借款(李健)", description = "/speedLoan")
public class SpeedLoanController {

    @Reference(version = "1.0.0")
    private SpeedLoanDubboService speedLoanService;

    @Reference(version = "1.0.0")
    private UserCreditDubboService creditDubboService;

    @Value("${h5-https-url}")
    private String h5HttpsUrl;
    private static final String SPEED_LOAN_APPLY_LOCK = "speedLoanApplyLock:";
    @Autowired
    private RedissonClient redissonClient;

    @PostMapping("/userDataStatus")
    @ApiOperation("极速借用户信息认证状态(李健)")
    public Result<UserDataStatusResponseVO> userDataStatus() {
        String userId = String.valueOf(PrincipalContext.getUserId());
        UserDataStatusResponseVO userDataStatusResponse = new UserDataStatusResponseVO();
        SpeedLoanUserDataStatusDTO speedLoanUserDataStatus = speedLoanService.getSpeedLoanUserDataStatus(userId);
        userDataStatusResponse.setPersonalInfoStatus(speedLoanUserDataStatus.getPersonalInfoStatus());
        userDataStatusResponse.setBankCardStatus(speedLoanUserDataStatus.getBankCardStatus());
        userDataStatusResponse.setIdentityInfoStatus(speedLoanUserDataStatus.getIdentityInfoStatus());
        userDataStatusResponse.setAuthStatus(speedLoanUserDataStatus.getAuthStatus());
        userDataStatusResponse.setZhimaAuthStatus(speedLoanUserDataStatus.getZhimaAuthStatus());
        userDataStatusResponse.setTelOperatorAuthStatus(speedLoanUserDataStatus.getTelOperatorAuthStatus());
        userDataStatusResponse.setSocialSecurityStatus(speedLoanUserDataStatus.getSocialSecurityStatus());
        userDataStatusResponse.setZhimaSwitchStatus(speedLoanUserDataStatus.getZhimaSwitchStatus());
        userDataStatusResponse.setSocialSecuritySwitchStatus(speedLoanUserDataStatus.getSocialSecuritySwitchStatus());
        userDataStatusResponse.setCreditCardStatus(speedLoanUserDataStatus.getCreditCardStatus());
        userDataStatusResponse.setSocialSecurityOrCreditCard(speedLoanUserDataStatus.getSocialSecurityOrCreditCard());

        return Result.with(userDataStatusResponse);
    }

    @PostMapping("/getSpeedLoanCreditAmount")
    @ApiOperation("获取/更新极速借授信额度(李健)")
    public Result<SpeedLoanCreditAmountResponseVO> getSpeedLoanCreditAmount(@RequestBody @Valid SpeedLoanCreditAmountReqeustVO speedLoanCreditAmountReqeust, HttpServletRequest request) {
        // 请求参数检测
        this.speedLoanCreditAmountReqeustCheck(speedLoanCreditAmountReqeust);
        String userId = String.valueOf(PrincipalContext.getUserId());
        LaunchSpeedLoanCreditRequestDTO requestDTO = new LaunchSpeedLoanCreditRequestDTO();
        requestDTO.setIpAddress(RequestUtil.getUserRealIP(request));
        requestDTO.setUserId(userId);
        requestDTO.setPlatformType(PlatformTypeEnum.NIIWOO.getType());
        BeanUtils.copyProperties(speedLoanCreditAmountReqeust, requestDTO);
        LaunchSpeedLoanCreditDTO launchSpeedLoanCredit = creditDubboService.launchSpeedLoanCredit(requestDTO);
        SpeedLoanCreditAmountResponseVO loanCreditAmountResponseVO = new SpeedLoanCreditAmountResponseVO();
        loanCreditAmountResponseVO.setFailCode(launchSpeedLoanCredit.getFailCode());
        loanCreditAmountResponseVO.setCreditOvertime(launchSpeedLoanCredit.getCreditOvertime());
        return Result.with(loanCreditAmountResponseVO);
    }

    @PostMapping("/speedLoanCreditResult")
    @ApiOperation("极速借授信相关信息(李健)")
    public Result<SpeedLoanCreditResultResponseVO> speedLoanCreditResult() {
        String userId = String.valueOf(PrincipalContext.getUserId());
        SpeedLoanCreditResultDTO speedLoanCreditResult = speedLoanService.getSpeedLoanCreditResult(userId);

        SpeedLoanCreditResultResponseVO creditResultResponse = new SpeedLoanCreditResultResponseVO();
        creditResultResponse.setCreditTotalAmount(speedLoanCreditResult.getCreditTotalAmount().intValue());
        creditResultResponse.setCreditStatus(speedLoanCreditResult.getCreditStatus());
        int creditAviAmountInt = speedLoanCreditResult.getCreditAviAmount().intValue();
        creditResultResponse.setCreditAviAmount(creditAviAmountInt < 0 ? 0 : creditAviAmountInt);
        creditResultResponse.setCreditOvertime(speedLoanCreditResult.getCreditOvertime());
        creditResultResponse.setPersonalInfoStatus(speedLoanCreditResult.getPersonalInfoStatus());
        creditResultResponse.setIdentityInfoStatus(speedLoanCreditResult.getIdentityInfoStatus());
        creditResultResponse.setBankCardStatus(speedLoanCreditResult.getBankCardStatus());
        creditResultResponse.setAuthStatus(speedLoanCreditResult.getAuthStatus());
        creditResultResponse.setZhimaAuthStatus(speedLoanCreditResult.getZhimaAuthStatus());
        creditResultResponse.setTelOperatorAuthStatus(speedLoanCreditResult.getTelOperatorAuthStatus());
        creditResultResponse.setSocialSecurityStatus(speedLoanCreditResult.getSocialSecurityStatus());
        creditResultResponse.setCreditCardStatus(speedLoanCreditResult.getCreditCardStatus());
        creditResultResponse.setSocialSecurityOrCreditCard(speedLoanCreditResult.getSocialSecurityOrCreditCard());
        return Result.with(creditResultResponse);
    }


    @PostMapping("/loanCostCalculation")
    @ApiOperation("极速借借款费用计算(砍头息)-鲁静")
    public Result<LoanFeeCalculationResponseVO> loanCostCalculation(@RequestBody @Valid LoanFeeCalculationRequestDTO request) {
        log.info("极速借借款费用计算(砍头息)"+JSONObject.toJSONString(request));
        String userId = String.valueOf(PrincipalContext.getUserId());
        //转换vo成dto给业务使用
        ConfirmLoanRequestDTO loanConfirmRequestDTO = new ConfirmLoanRequestDTO();
        loanConfirmRequestDTO.setUserId(userId);
        loanConfirmRequestDTO.setLoanAmount(request.getLoanAmount());
        loanConfirmRequestDTO.setLoanTerm(request.getLoanTerm());
        loanConfirmRequestDTO.setLoanUsage(request.getLoanUsage());
        loanConfirmRequestDTO.setConfigType(ProjectTypeEnum.PERSONAL_SPEEDLOAN.getValue());
        //调用dubbo接口
        ConfirmResponseDTO loanConfirmResponseDTO = speedLoanService.calculateConfirm(loanConfirmRequestDTO);
        //封装vo接口返回给前台展示
        LoanFeeCalculationResponseVO speedLoanFeeCalculationResponseVO = new LoanFeeCalculationResponseVO();
        speedLoanFeeCalculationResponseVO.setHandAmount(loanConfirmResponseDTO.getHandAmount());
        speedLoanFeeCalculationResponseVO.setPlatformManagerFee(loanConfirmResponseDTO.getPlatformManageFee());
        speedLoanFeeCalculationResponseVO.setGuaranteServiceFee(loanConfirmResponseDTO.getGuaranteServiceFee());
        speedLoanFeeCalculationResponseVO.setLoanInterest(loanConfirmResponseDTO.getLoanInterestFee());
        speedLoanFeeCalculationResponseVO.setBorrowerRate(loanConfirmResponseDTO.getLoanInterestRate());
        speedLoanFeeCalculationResponseVO.setLoanTerm(loanConfirmResponseDTO.getLoanTerm());
        speedLoanFeeCalculationResponseVO.setRepaymentTotalAmount(loanConfirmResponseDTO.getTotalRepayAmount());
        speedLoanFeeCalculationResponseVO.setRepaymentWay(loanConfirmResponseDTO.getRepaymentWay().getValue());
        speedLoanFeeCalculationResponseVO.setOverdueFeeRate(loanConfirmResponseDTO.getOverdueFeeRate());
        speedLoanFeeCalculationResponseVO.setPlatformManageFeeRate(loanConfirmResponseDTO.getPlatformManageFeeRate());
        speedLoanFeeCalculationResponseVO.setGuaranteeServiceFeeRate(loanConfirmResponseDTO.getGuaranteeServiceFeeRate());

        return Result.with(speedLoanFeeCalculationResponseVO);
    }



    @PostMapping("/repaymentPlan")
    @ApiOperation("借款确认页面-还款详情(砍头息)-鲁静")
    public Result<List<RepaymentPlanResponseVO>> repaymentPlan(@RequestBody @Valid LoanRepaymentPlanRequestDTO request) {
        log.info("借款确认页面-还款详情(砍头息)"+JSONObject.toJSONString(request));
        String userId = String.valueOf(PrincipalContext.getUserId());
        //转换vo成dto给业务使用
        ConfirmLoanRepaymentPlanRequestDTO loanConfirmRequestDTO = new ConfirmLoanRepaymentPlanRequestDTO();
        loanConfirmRequestDTO.setUserId(userId);
        loanConfirmRequestDTO.setLoanAmount(request.getLoanAmount());
        loanConfirmRequestDTO.setLoanTerm(request.getLoanTerm());
        loanConfirmRequestDTO.setConfigType(RateConfigTypeEnum.SPEED_LOAN.getType());
        //调用dubbo接口
        List<RepaymentPlanDTO> repaymentPlanDTOList = speedLoanService.repaymentPlan(loanConfirmRequestDTO);
        List<RepaymentPlanResponseVO> responseVOS = new ArrayList<>();
        //封装vo接口返回给前台展示
        if(!repaymentPlanDTOList.isEmpty()){
            log.info("借款确认页面-还款详情返回{}",JSONObject.toJSONString(repaymentPlanDTOList));
            for (RepaymentPlanDTO repaymentPlanDTO:repaymentPlanDTOList){
                RepaymentPlanResponseVO responseVO = new RepaymentPlanResponseVO();
                responseVO.setCurrentPeriod(repaymentPlanDTO.getCurrentPeriod());
                responseVO.setGuaranteeServiceFee(repaymentPlanDTO.getGuaranteeServiceFee());
                responseVO.setInterest(repaymentPlanDTO.getInterest());
                responseVO.setPlanType(repaymentPlanDTO.getPlanType());
                responseVO.setPlatformManageFee(repaymentPlanDTO.getPlatformManageFee());
                responseVO.setPrincipal(repaymentPlanDTO.getPrincipal());
                responseVO.setPrincipalInterest(repaymentPlanDTO.getPrincipalInterest());
                responseVO.setRefundDate(repaymentPlanDTO.getRefundDate());
                responseVO.setRepaymentTotalAmount(repaymentPlanDTO.getRepaymentTotalAmount());
                responseVO.setTotalPeriod(repaymentPlanDTO.getTotalPeriod());
                responseVOS.add(responseVO);
            }
        }
        return Result.with(responseVOS);
    }

    @PostMapping("/speedLoanConfiguration")
    @ApiOperation("我的借款配置(吴科)")
    public Result<SpeedLoanConfigResponseVO> speedLoanConfiguration() {
        log.info("LoanController.speedLoanConfiguration start");
        String userId = String.valueOf(PrincipalContext.getUserId());
        log.info("LoanController.speedLoanConfiguration.userId={}",userId);
        SpeedLoanConfigurationResponseDTO responseDTO = speedLoanService.speedLoanConfiguration(userId);
        String responseDTOString = JSON.toJSONString(responseDTO);
        SpeedLoanConfigResponseVO responseVO = JSON.parseObject(responseDTOString,SpeedLoanConfigResponseVO.class);
        log.info("LoanController.speedLoanConfiguration.userId={},responseVO={}",userId,JSON.toJSONString(responseVO));
        return Result.with(responseVO);
    }

    @PostMapping("/intoSpeedLoanCheck")
    @ApiOperation("借款检测(吴科)")
    public Result<SpeedLoanApplyCommonResponseVO> intoSpeedLoanCheck(@RequestBody @Valid SpeedLoanPublishCheckRequestVO speedLoanPublishCheckRequestVO) {
        log.info("speedLoanPublishCheck.speedLoanPublishCheckRequestVO={}",JSON.toJSONString(speedLoanPublishCheckRequestVO));
        String userId = String.valueOf(PrincipalContext.getUserId());
        log.info("LoanController.speedLoanPublishCheck.userId={}",userId);
        SpeedLoanPublishCheckRequestDTO dubboRequestDTO = new SpeedLoanPublishCheckRequestDTO();
        BeanUtils.copyProperties(speedLoanPublishCheckRequestVO,dubboRequestDTO);
        dubboRequestDTO.setUserId(userId);
        SpeedLoanApplyCommonResponseDTO speedLoanApplyCommonResponseDTO = speedLoanService.speedLoanPublishCheck(dubboRequestDTO);
        SpeedLoanApplyCommonResponseVO vo = new SpeedLoanApplyCommonResponseVO();
        BeanUtils.copyProperties(speedLoanApplyCommonResponseDTO,vo);
        vo.setExtendData(speedLoanApplyCommonResponseDTO.getExtendData());
        vo.setCheckStatus(speedLoanApplyCommonResponseDTO.getStatus());
        log.info("LoanController.speedLoanPublishCheck.userId={},vo={}",userId,JSON.toJSONString(vo));
        return Result.with(vo);
    }

    @PostMapping("/speedLoanConfirmSubmitCheck")
    @ApiOperation("借款确认提交检查")
    public Result<SpeedLoanApplyCommonResponseVO> speedLoanConfirmSubmitCheck(@RequestBody @Valid SpeedLoanConfirmSubmitCheckRequestVO speedLoanConfirmSubmitCheckRequestVO){
        log.info("speedLoanConfirmSubmitCheck.speedLoanConfirmSubmitCheckRequestVO={}",JSON.toJSONString(speedLoanConfirmSubmitCheckRequestVO));
        SpeedLoanApplyCommonResponseVO vo = new SpeedLoanApplyCommonResponseVO();
        if(ProjectApplyCheckTypeEnum.NEW_PROJ_SUBMIT_CHECK.getCheckType()!=speedLoanConfirmSubmitCheckRequestVO.getCheckType()){
            log.info("speedLoanConfirmSubmitCheck非新标的提交无需检查");
            return Result.with(vo);
        }
        SpeedLoanApplyCommonResponseDTO resposeDTO = speedLoanService.speedLoanConfirmSubmitCheck(speedLoanConfirmSubmitCheckRequestVO.getDeadline());
        BeanUtils.copyProperties(resposeDTO,vo);
        vo.setCheckStatus(resposeDTO.getStatus());
        return Result.with(vo);
    }

    @PostMapping("/speedLoanApply")
    @ApiOperation("申请极速借借款(吴科)")
    public Result<SpeedLoanApplyCommonResponseVO> speedLoanApply(@RequestBody @Valid SpeedLoanApplyRequestVO speedLoanApplyRequestVO,HttpServletRequest request) {
        log.info("speedLoanApply.speedLoanApplyRequestVO={}",JSON.toJSONString(speedLoanApplyRequestVO));
        String userId = String.valueOf(PrincipalContext.getUserId());
        final String speedLoanApplyLockKey = SPEED_LOAN_APPLY_LOCK+userId;
        RLock lock = redissonClient.getLock(speedLoanApplyLockKey);
        this.speedLoanApplyLock(lock);
        SpeedLoanApplyCommonResponseVO vo;
        try {
            String userRealIP = RequestUtil.getUserRealIP(request);
            log.info("LoanController.speedLoanApply.userId={}",userId);

            SpeedLoanApplyRequestDTO speedLoanApplyRequestDTO = new SpeedLoanApplyRequestDTO();
            BeanUtils.copyProperties(speedLoanApplyRequestVO,speedLoanApplyRequestDTO);

            Optional<SpeedLoanApplyRequestVO> speedLoanApplyRequestOpt = Optional.ofNullable(speedLoanApplyRequestVO);
            speedLoanApplyRequestDTO.setAddressInfoDTOList(this.initAddressInfo(speedLoanApplyRequestOpt));
            speedLoanApplyRequestDTO.setDeviceInfo(this.initDeviceInfo(speedLoanApplyRequestOpt,userRealIP));

            speedLoanApplyRequestDTO.setUserId(userId);
            SpeedLoanApplyCommonResponseDTO speedLoanApplyCommonResponseDTO = speedLoanService.speedLoanApply(speedLoanApplyRequestDTO);
            vo = this.convertResponseVO(speedLoanApplyCommonResponseDTO);
            log.info("LoanController.speedLoanApply.userId={},vo={}",userId,JSON.toJSONString(vo));
        } finally {
            //释放锁
            speedLoanApplyUnLock(lock);
        }
        return Result.with(vo);
    }

    private void speedLoanApplyLock(RLock lock){
        boolean tryLockResult = false;
        try {
            tryLockResult = lock.tryLock(-1, 110000, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            log.error("speedLoanApplyLock借款提交获取锁异常！",e);
            throw new RuntimeException("服务器异常，请稍后再试");
        }
        if(!tryLockResult){
            log.info("speedLoanApplyLock借款提交获取锁-锁已被占用！");
            throw new BizException("TRD90002");
        }
    }

    private void speedLoanApplyUnLock(RLock lock){
        Optional.ofNullable(lock).ifPresent(l->l.unlock());
    }

    @PostMapping("/speedLoanApplyForBack")
    @ApiOperation("退回标的申请极速借借款(吴科)")
    public Result<SpeedLoanApplyCommonResponseVO> speedLoanApplyForBack(@RequestBody @Valid SpeedLoanApplyForBackRequestVO speedLoanApplyForBackRequestVO,HttpServletRequest request) {
        log.info("speedLoanApplyForBack.speedLoanApplyForBackRequestVO={}",JSON.toJSONString(speedLoanApplyForBackRequestVO));
        String userId = String.valueOf(PrincipalContext.getUserId());
        final String speedLoanApplyLockKey = SPEED_LOAN_APPLY_LOCK+userId;
        RLock lock = redissonClient.getLock(speedLoanApplyLockKey);
        this.speedLoanApplyLock(lock);
        SpeedLoanApplyCommonResponseVO vo;
        try {
            String userRealIP = RequestUtil.getUserRealIP(request);
            log.info("LoanController.speedLoanApplyForBack.userId={}",userId);

            SpeedLoanApplyForBackRequestDTO speedLoanApplyForBackRequestDTO = new SpeedLoanApplyForBackRequestDTO();
            BeanUtils.copyProperties(speedLoanApplyForBackRequestVO,speedLoanApplyForBackRequestDTO);

            Optional<SpeedLoanApplyRequestVO> speedLoanApplyRequestOpt = Optional.ofNullable(speedLoanApplyForBackRequestVO);
            speedLoanApplyForBackRequestDTO.setAddressInfoDTOList(this.initAddressInfo(speedLoanApplyRequestOpt));
            speedLoanApplyForBackRequestDTO.setDeviceInfo(this.initDeviceInfo(speedLoanApplyRequestOpt,userRealIP));

            speedLoanApplyForBackRequestDTO.setUserId(userId);

            SpeedLoanApplyCommonResponseDTO speedLoanApplyCommonResponseDTO = speedLoanService.speedLoanApplyForBack(speedLoanApplyForBackRequestDTO);
            vo = this.convertResponseVO(speedLoanApplyCommonResponseDTO);
        } finally {
            //释放锁
            speedLoanApplyUnLock(lock);
        }
        log.info("LoanController.speedLoanApplyForBack.userId={},vo={}",userId,JSON.toJSONString(vo));
        return Result.with(vo);
    }

    private List<SpeedLoanApplyRequestDTO.AddressInfoRequestDTO> initAddressInfo(Optional<SpeedLoanApplyRequestVO> speedLoanApplyRequestOpt){
        return speedLoanApplyRequestOpt.map(SpeedLoanApplyRequestVO::getAddressInfoVOList).map(addressInfoVOList -> {
            List<SpeedLoanApplyRequestDTO.AddressInfoRequestDTO> dtoList = new ArrayList<>();
            addressInfoVOList.forEach(addressInfoVO->{
                SpeedLoanApplyRequestDTO.AddressInfoRequestDTO dto = new SpeedLoanApplyRequestDTO.AddressInfoRequestDTO();
                BeanUtils.copyProperties(addressInfoVO,dto);
                dtoList.add(dto);
            });
            return dtoList;
        }).orElse(null);
    }

    private SpeedLoanApplyRequestDTO.DeviceInfoRequestDTO initDeviceInfo(Optional<SpeedLoanApplyRequestVO> speedLoanApplyRequestOpt,String userRealIP){
        return speedLoanApplyRequestOpt.map(SpeedLoanApplyRequestVO::getDeviceInfo).map(deviceInfoRequestVO -> {
            SpeedLoanApplyRequestDTO.DeviceInfoRequestDTO deviceInfoRequestDTO = new SpeedLoanApplyRequestDTO.DeviceInfoRequestDTO();
            BeanUtils.copyProperties(deviceInfoRequestVO,deviceInfoRequestDTO);
            deviceInfoRequestDTO.setIp(userRealIP);
            return deviceInfoRequestDTO;
        }).orElse(null);
    }

    private SpeedLoanApplyCommonResponseVO convertResponseVO(SpeedLoanApplyCommonResponseDTO speedLoanApplyCommonResponseDTO){
        SpeedLoanApplyCommonResponseVO vo = new SpeedLoanApplyCommonResponseVO();
        BeanUtils.copyProperties(speedLoanApplyCommonResponseDTO,vo);
        vo.setExtendData(speedLoanApplyCommonResponseDTO.getExtendData());
        vo.setCheckStatus(speedLoanApplyCommonResponseDTO.getStatus());
        return vo;
    }

    @PostMapping("/speedLoanQueryForBack")
    @ApiOperation("退回标的信息查询(吴科)")
    public Result<SpeedLoanQueryForBackResponseVO> speedLoanQueryForBack() {
        String userId = String.valueOf(PrincipalContext.getUserId());
        log.info("LoanController.speedLoanQueryForBack.userId={}",userId);
        SpeedLoanQueryResponseDTO speedLoanQueryResponseDTO = speedLoanService.speedLoanQueryForBack(userId);

        if(speedLoanQueryResponseDTO==null){
            return Result.with(null);
        }
        SpeedLoanQueryForBackResponseVO vo = new SpeedLoanQueryForBackResponseVO();
        BeanUtils.copyProperties(speedLoanQueryResponseDTO,vo);
        vo.setTitle(ProjectInfoUtil.getLoanUsage(vo.getTitle()));

        SpeedLoanQueryResponseDTO.DetailBack detailBack = speedLoanQueryResponseDTO.getDetailBack();
        if(detailBack!=null){
            SpeedLoanQueryForBackResponseVO.DetailBack detailBackVO = new SpeedLoanQueryForBackResponseVO.DetailBack();
            BeanUtils.copyProperties(detailBack,detailBackVO);
            vo.setDetailBack(detailBackVO);
        }

        log.info("LoanController.speedLoanQueryForBack.userId={},vo={}",userId,JSON.toJSONString(vo));
        return Result.with(vo);
    }

    @PostMapping("/contractPreviewInfo")
    @ApiOperation("借款相关协议数据(李健)")
    public Result<ContractPreviewInfoVO> contractPreviewInfo() {
        String userId = String.valueOf(PrincipalContext.getUserId());
        ContractPreviewInfoDTO contractPreviewInfo = null;
        try {
            contractPreviewInfo = speedLoanService.getContractPreviewInfo(userId);
        } catch (Exception e) {
            log.error("借款相关协议数据,远程调用服务失败:", e);
        }
        ContractPreviewInfoVO contractPreviewInfoVO = new ContractPreviewInfoVO();
        BeanUtils.copyProperties(contractPreviewInfo, contractPreviewInfoVO);

        return Result.with(contractPreviewInfoVO);
    }

    @PostMapping("/loanPreviewContractUrl")
    @ApiOperation("借款预览合同地址(李健)")
    public Result<List<LoanContractUrlVo>> loanPreviewContractUrl() {
        List<LoanContractUrlVo> loanContractUrlList = new ArrayList<>();

        // H5合同地址
        /*loanContractUrlList.add(new LoanContractUrlVo("居间借款合同", h5HttpsUrl + "/html5/project/niiwoo-contract/loanAgreement.html"));
        loanContractUrlList.add(new LoanContractUrlVo("还款服务委托书", h5HttpsUrl + "/html5/project/niiwoo-contract/repayAgreement.html"));
        //loanContractUrlList.add(new LoanContractUrlVo("仲裁补充协议", h5HttpsUrl + "/html5/project/niiwoo-contract/arbitrateAgreement.html"));
        //loanContractUrlList.add(new LoanContractUrlVo("授权委托书", h5HttpsUrl + "/html5/project/niiwoo-contract/authAgreement.html"));
        //loanContractUrlList.add(new LoanContractUrlVo("反担保保证合同", h5HttpsUrl + "/html5/project/niiwoo-contract/unGuarantAgreement.html"));
        loanContractUrlList.add(new LoanContractUrlVo("借款人提示函", h5HttpsUrl + "/html5/project/niiwoo-contract/borrowerPromptAgreement.html"));
        loanContractUrlList.add(new LoanContractUrlVo("电子签章使用授权书", h5HttpsUrl + "/html5/project/contract/electronicSignaturePreview/index.html"));*/

        //5.5.0换了 地址，
        loanContractUrlList.add(new LoanContractUrlVo("居间借款合同", h5HttpsUrl + "/html5/contract/jujian_gr.html"));
        loanContractUrlList.add(new LoanContractUrlVo("还款服务委托书", h5HttpsUrl + "/html5/contract/repayAgreement.html"));
        //loanContractUrlList.add(new LoanContractUrlVo("仲裁补充协议", h5HttpsUrl + "/html5/project/niiwoo-contract/arbitrateAgreement.html"));
        //loanContractUrlList.add(new LoanContractUrlVo("授权委托书", h5HttpsUrl + "/html5/project/niiwoo-contract/authAgreement.html"));
        //loanContractUrlList.add(new LoanContractUrlVo("反担保保证合同", h5HttpsUrl + "/html5/project/niiwoo-contract/unGuarantAgreement.html"));
        loanContractUrlList.add(new LoanContractUrlVo("借款人提示函", h5HttpsUrl + "/html5/contract/borrowerPromptAgreement.html"));
        loanContractUrlList.add(new LoanContractUrlVo("电子签章使用授权书", h5HttpsUrl + "/html5/contract/signing.html"));
        loanContractUrlList.add(new LoanContractUrlVo("征信查询授权书",h5HttpsUrl + "/html5/contract/credit.html"));
        return Result.with(loanContractUrlList);
    }

    @PostMapping("/fadadaWithholdContractSign")
    @ApiOperation("还款服务委托书生成(吴科)")
    public Result<FadadaWithholdContractSignResponseVO> fadadaWithholdContractSign(FadadaWithholdContractSignRequestVO fadadaWithholdContractSignRequestVO) {
        log.info("LoanController.fadadaWithholdContractSign start");
        log.info("LoanController.fadadaWithholdContractSign fadadaWithholdContractSignRequestVO={}",JSON.toJSONString(fadadaWithholdContractSignRequestVO));
        String userId = String.valueOf(PrincipalContext.getUserId());
        log.info("LoanController.fadadaWithholdContractSign userId={}",userId);
        speedLoanService.fadadaWithholdContractSign(userId,fadadaWithholdContractSignRequestVO.getProjectId());
        log.info("LoanController.fadadaWithholdContractSign userId={} end",userId);
        FadadaWithholdContractSignResponseVO vo = new FadadaWithholdContractSignResponseVO();
        return Result.with(vo);
    }
    
    @PostMapping("/r360ConfirmLoan")
    @ApiOperation("融360标的在你我金融APP上确认借款(贾波)")
	public Empty r360ConfirmLoan(@RequestBody @Valid R360ConfirmLoanRequestVO r360ConfirmLoanRequestVO) {
        log.info("r360ConfirmLoan.r360ConfirmLoanRequestVO={}",JSON.toJSONString(r360ConfirmLoanRequestVO));
        String userId = String.valueOf(PrincipalContext.getUserId());
        log.info("r360ConfirmLoan.r360ConfirmLoanRequestVO.userId={}",userId);

        R360ConfirmLoanRequestDTO requestDTO = new R360ConfirmLoanRequestDTO();
        requestDTO.setProjectId(r360ConfirmLoanRequestVO.getProjectId());
        requestDTO.setUserId(userId);
        requestDTO.setConfirmSource(ConfirmLoanSourceEnum.NIIWOO_CONFIRMED.getCode());
        requestDTO.setDeadline(r360ConfirmLoanRequestVO.getDeadline());
        requestDTO.setLoanAmount(r360ConfirmLoanRequestVO.getLoanAmount());
        
        log.info("speedLoanService.confirmLoan={}",JSON.toJSONString(requestDTO));
        speedLoanService.confirmLoan(requestDTO);
		log.info("speedLoanService.confirmLoan调用成功");
        
        return Empty.getInstance();
    }


    @PostMapping("/fastBorrowAccreditCity")
    @ApiOperation("借款服务开放城市")
    public Result<List<FastBorrowAccreditCityResponseVO>> fastBorrowAccreditCity() {
        List<FastBorrowAccreditCityResponseVO> responseVOList = new ArrayList<>();
        List<FastBorrowAccreditCityResponseDTO> responseDTOList = speedLoanService.fastBorrowAccreditCity();

        for(FastBorrowAccreditCityResponseDTO responseDTO : responseDTOList){
            FastBorrowAccreditCityResponseVO responseVO = new FastBorrowAccreditCityResponseVO();
            FastBorrowAccreditCityResponseVO.AccreditCity accreditCity = null;
            responseVO.setProvinceName(responseDTO.getProvinceName());
            for(FastBorrowAccreditCityResponseDTO.AccreditCity accreditCityDTO : responseDTO.getCitys()){
                accreditCity = new FastBorrowAccreditCityResponseVO.AccreditCity();
                accreditCity.setCity(accreditCityDTO.getCity());
                responseVO.getCitys().add(accreditCity);
            }
            responseVOList.add(responseVO);
        }
        return Result.with(responseVOList);
    }

    private void speedLoanCreditAmountReqeustCheck(SpeedLoanCreditAmountReqeustVO speedLoanCreditAmountReqeust) {
        if(speedLoanCreditAmountReqeust.getCaller() != 1 && speedLoanCreditAmountReqeust.getCaller() != 2 && speedLoanCreditAmountReqeust.getCaller() != 3) {
            throw new BizException("TRD10005");
        }
        if(speedLoanCreditAmountReqeust.getMapType() != null && speedLoanCreditAmountReqeust.getMapType() != 0 && speedLoanCreditAmountReqeust.getMapType() != 1) {
            throw new BizException("TRD10005");
        }
        if(speedLoanCreditAmountReqeust.getEquipmentStatus() != null && speedLoanCreditAmountReqeust.getEquipmentStatus() != 0 && speedLoanCreditAmountReqeust.getEquipmentStatus() != 1) {
            throw new BizException("TRD10005");
        }
    }


}
